import { ApiCall, BaseConnection, TsrpcErrorType } from "tsrpc";
import { ClientAction, ClientInfo } from "../../shared/api_bot/IMassage";
import { server_WebClient, server_back, server_bot } from "../..";
import { MsgMessage } from "../../shared/api_bot/MsgMessage";
import UserManager from "./UserManager";
import sdk from '../index';
import { BaseConf } from "../../shared/api_client/base";
import { BaseRequest } from "../../shared/api_bot/base";
import { ReqMessage } from "../../shared/api_bot/PtlMessage";
import client_component from "../../component/client_component";
import { ComType } from "../tool/component";
import mail_component from "../../component/mail_component";
const cron = require('node-cron');
/**
 * 客户端 连接管理
 */
class ClientManage {
    connMap: Map<string, BaseConnection<any>> = new Map();
    clientConnMap: Map<string, { info: ClientInfo, id: string }> = new Map();
    // 等待 验证token
    waitTokenMap: Map<string, { id: string, expiredTime: number }> = new Map();
    passTokenMap: Map<string, { id: string, expiredTime: number }> = new Map();
    constructor() {
        this.connMap = new Map();
    }
    async init() {
        console.log('ClientManage init');
        let data = await sdk.db.find('token');
        if (data.length > 0) {
            for (let i = 0; i < data.length; i++) {
                let e = data[i];
                this.passTokenMap.set(e.token, { id: e.id, expiredTime: e.expiredTime });
            }
        }
        this.flows_long();
        this.flows_short();
    }
    // 长连接 - bot端
    private flows_long() {
        server_bot.flows.preMsgCallFlow.push(async (msg) => {

            return msg;
        })
        server_bot.flows.postDisconnectFlow.push(async (data) => {
            this.connMap.delete(data.conn.id);
            console.log(`客户端连接数   : ${this.connMap.size}`);
            return data;
        });
        server_bot.flows.postConnectFlow.push(async (conn) => {
            this.connMap.set(conn.id, conn);
            console.log(`客户端连接数   : ${this.connMap.size}`);

            return conn;
        })
        server_bot.flows.preApiCallFlow.push(async (call) => {
            let data = call.req as ReqMessage;
            let ClientInfo = data.ClientInfo;
            let Message = data.Message;
            let UserInfo = data.UserInfo;
            if (!ClientInfo && !Message && !UserInfo) {
                call.error({
                    message: 'req property is not empty',
                    type: TsrpcErrorType.ApiError,
                });
                return undefined;
            }
            if (ClientInfo.platform == 'qq') {
                Message.content = Message.content.replace(/<at[^>]*>/g, '').replace(/\//g, '').replace(/\s+/g, ' ').trim();
                UserInfo.name = '匿名';
            }
            // qqguild 平台
            // <at id="475496778575011243"> 属性
            if (ClientInfo.platform == 'qqguild') {
                Message.content = Message.content.replace(/<at[^>]*>/g, '').replace(/\//g, '').replace(/\s+/g, ' ').trim();
            }

            let info = { name: ClientInfo.platform, id: UserInfo.id };
            let player = await UserManager.getPlayer(info);
            if (!player) {
                player = await UserManager.create(info);
            }
            data._player = player;
            if (ClientInfo) {
                this.addClient(call.conn, ClientInfo);
            }
            let com = player.getComponent(ComType.client) as client_component;
            let pullEmail = false;
            if (com) {
                if (com.lastActiveTime < Date.now() - 1000 * 60 * 5) {
                    pullEmail = true;
                }
                com.update_client(ClientInfo);
                com.update_message(Message);
            } else {
                pullEmail = true;
            }
            if (pullEmail) {
                let com = player.getComponent(ComType.邮件) as mail_component;
                com.pull();
            }
            return call;
        })
    }
    // 短连接 - 网页端
    private flows_short() {
        const callFunc = async (call: ApiCall<any, any, any>) => {
            // 公开接口
            const cfg = call.service.conf as BaseConf;
            if (call.service.name.includes('open/')) {
                return call;
            }
            if (cfg?._notLoadPlayer) {
                return call;
            }

            if (!call.req._token) {
                call.error({
                    message: '请先登录',
                    type: TsrpcErrorType.ApiError,
                });
                return undefined;
            }
            let data = this.checkToken(call.req._token);
            if (!data) {
                call.error({
                    message: '请先登录',
                    type: TsrpcErrorType.ApiError,
                });
                return undefined;
            }
            if (!cfg?._notCheckOff) {
                let player = UserManager.getOnlinePlayer(data.id);
                if (!player && cfg?._notLoadPlayer) {
                    call.error({
                        message: '角色未在线，请艾特一次机器人',
                        type: TsrpcErrorType.ApiError,
                    });
                    return undefined;
                }
                if (!player) {
                    player = await UserManager.loadPlayerFromDB(data.id);
                    if (!player) {
                        call.error({
                            message: '未注册账号',
                            type: TsrpcErrorType.ApiError,
                        });
                        return undefined;
                    }
                }

                call.req._player = player;
            }

            return call;
        }
        server_back.flows.preApiCallFlow.push(callFunc);
        server_WebClient.flows.preApiCallFlow.push(callFunc);
    }
    passToken(token: string) {
        let data = this.waitTokenMap.get(token);
        if (data) {
            data.expiredTime = Date.now() + 30 * 24 * 60 * 60 * 1000;
            this.passTokenMap.set(token, data);
            this.waitTokenMap.delete(token);
            sdk.db.update('token', { id: data.id }, { ...data, token: token });
        }
    }
    checkToken(token: string) {
        let data = this.passTokenMap.get(token);
        return data;
    }
    sendMsg(clientInfo: ClientInfo, msg: MsgMessage) {
        let conn = this.getConn(clientInfo);
        if (!conn) {
            console.log(`[未连接]\n${msg.data}\n----------`);
            return;
        }
        console.log(`[发送消息]\n${msg.data}\n----------`);

        if (clientInfo.platform == 'qq' && msg.action == ClientAction.text) {
            msg.data = '✉️新消息\n' + msg.data;
        }
        conn.sendMsg('Message', msg);
    }
    private getConn(clientInfo: ClientInfo) {
        let key = `${clientInfo.id}_${clientInfo.platform}`;
        let client = this.clientConnMap.get(key);
        if (!client) {
            console.log(`getConn:不存在的客户端:${key}`);
            return;
        }
        return this.connMap.get(client.id);
    }
    addClient(conn: BaseConnection<any>, clientInfo: ClientInfo) {
        let key = `${clientInfo.id}_${clientInfo.platform}`;

        if (!this.clientConnMap.has(key)) {
            console.log(`客户端bot 增加
名称:${clientInfo.name}
平台:${clientInfo.platform}
BOT数量:${this.clientConnMap.size + 1}`);

        }
        this.clientConnMap.set(key, { info: clientInfo, id: conn.id });
    }
}
export default new ClientManage();
